package com.bcst.factory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 *@description 欢迎关注公众号 编程识堂,每日更新技术相关文章，关注我不迷路
 *@author 小堂
 *@create 2023/9/2 18:07
 */
public class BeanFactory {

    /**
     * ⼯⼚类的两个任务
     * 任务⼀：加载解析xml，读取xml中的bean信息，通过反射技术实例化bean对象，然后放⼊
     map待⽤
     * 任务⼆：提供接⼝⽅法根据id从map中获取bean（静态⽅法）
     */
    private static Map<String,Object> map = new HashMap<>();

    static {
        InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(inputStream);
            Element rootElement = document.getRootElement();
            List<Element> list = rootElement.selectNodes("//bean");
            //实例化bean对象
            for (Element element : list) {
                String id = element.attributeValue("id");
                String classStr = element.attributeValue("class");
                Class<?> alc = Class.forName(classStr);
                Object instance = alc.newInstance();
                map.put(id,instance);
            }
            // 维护bean之间的依赖关系
            List propertyList = rootElement.selectNodes("//property");
            for (int i = 0; i < propertyList.size(); i++) {
                Element element = (Element) propertyList.get(i);
                // 处理property元素
                String name = element.attributeValue("id");
                String ref = element.attributeValue("ref");
                Element elementParent = element.getParent();
                Object parentObj = map.get(elementParent.attributeValue("id"));
                Method[] methods = parentObj.getClass().getMethods();
                for (Method method : methods) {
                    if (method.getName().equalsIgnoreCase("set"+name)){
                        method.invoke(parentObj,map.get(ref));
                    }
                }

            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String id){
        return map.get(id);
    }

}
